package cn.ronghuanet.gift.service.impl;

import cn.ronghuanet.gift.domain.TenantType;
import cn.ronghuanet.gift.mapper.TenantTypeMapper;
import cn.ronghuanet.gift.service.ITenantTypeService;
import com.baomidou.mybatisplus.mapper.Wrapper;
import com.baomidou.mybatisplus.service.impl.ServiceImpl;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;

/**
 * <p>
 *  服务实现类
 * </p>
 *
 * @author ysosang
 * @since 2022-12-06
 */
@Service
public class TenantTypeServiceImpl extends ServiceImpl<TenantTypeMapper, TenantType> implements ITenantTypeService {

    @Autowired
    private RedisTemplate redisTemplate;
    //redis的key
    public static final String TENANT_TYPES_CACHE_IN_REDIS = "tenant_types_cache_in_redis";

    @Autowired
    private RedissonClient redissonClient;
    @Override
    public List<TenantType> selectList(Wrapper<TenantType> wrapper) {

        //从redis中查询,如果有直接返回 10000
        Object o = redisTemplate.opsForValue().get(TENANT_TYPES_CACHE_IN_REDIS);
        if (Objects.nonNull(o))
            return (List<TenantType>) o;

        RLock lock = redissonClient.getLock(TENANT_TYPES_CACHE_IN_REDIS);
        try {
            lock.lock();
            o = redisTemplate.opsForValue().get(TENANT_TYPES_CACHE_IN_REDIS);
            if (Objects.nonNull(o))
                return (List<TenantType>) o;
            //如果没有从数据库中查询并返回
            List<TenantType> tenantTypes = super.selectList(wrapper);
            if (tenantTypes==null || tenantTypes.size()<1) //如果数据库没有,设置一个[],放入缓存并返回
                tenantTypes = new ArrayList<>();
            redisTemplate.opsForValue().set(TENANT_TYPES_CACHE_IN_REDIS, tenantTypes);
            return tenantTypes;
        } catch (Exception e) {
            e.printStackTrace();
        }finally {
            if (lock != null) {
                lock.unlock();
            }
        }
        return null;

    }

    //缓存的三大问题
    //1 缓存的穿透:缓存和数据库都没有(id=-1),高并发直接打到数据库
    //解决方案:1 合法性判断(不存在) 2 返回一个默认值 3 布隆过滤器
    //2 缓存击穿: 某个数据库缓存没有(做增删改的删除缓存),大量的请求打到数据库库
        //互斥锁
        //不设置过期时间
    //不需要处理雪崩  双重判断,一种缓存只打一个到数据库,不存在雪崩!
    //3 缓存的雪崩: 多个数据库缓存同时没有,少量的请求累积成大量请求
        //不设置过期时间
        //双key
    //===============做完增删改要删除缓存=================//
    @Override
    public boolean insert(TenantType entity) {
        super.insert(entity);
        //delayDoubleDel();


        redisTemplate.delete(TENANT_TYPES_CACHE_IN_REDIS);
        //第二次删除交给canal监控删除
        return true;
    }

    @Override
    public boolean deleteById(Serializable id) {
        super.deleteById(id);
        //delayDoubleDel();

        redisTemplate.delete(TENANT_TYPES_CACHE_IN_REDIS);
        //第二次删除交给canal监控删除
        return true;

    }

    @Override
    public boolean updateById(TenantType entity) {
        super.updateById(entity);
        //delayDoubleDel();

        redisTemplate.delete(TENANT_TYPES_CACHE_IN_REDIS);
        //第二次删除交给canal监控删除
        return true;

    }

    //延时双删
    private void delayDoubleDel() {
        redisTemplate.delete(TENANT_TYPES_CACHE_IN_REDIS);
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        redisTemplate.delete(TENANT_TYPES_CACHE_IN_REDIS);
    }
    //===============做完增删改要删除缓存=================//

    public synchronized void main1(String[] args) {
        System.out.println("jfjjfjfj");
        main2(args);
        System.out.println("jfjjfjfj");
    }

    public synchronized void main2(String[] args) {
    }
}
